#pragma once
#include "Variable.h"
#include "Sentencia.h"
class Asignar:
	public Sentencia
{
public:

	Asignar(Sentencia *next,Variable* variable,Expr* expr):Sentencia(next)
	{
		this->expr=expr;
		this->variable=variable;
	}

	~Asignar(void)
	{
	}

	void setVariable(Variable* variable){
		this->variable=variable;
	}
	void setExpr(Expr* expr){
		this->expr=expr;
	}

	Variable* getVariable(){
		return this->variable;
	}

	Expr* getExpr(){
		return this->expr;
	}
	virtual string is(){
		return "ASIGNAR";
	}

	void validarRegistros(registro *tts_v,registro *tts_e){
		if(tts_v->getTs()->getTable().size()==tts_e->getTs()->getTable().size()){
					for(int i=0;i<(int)tts_v->getTs()->getTable().size();i++){
						if(tts_v->getTs()->getTable().at(i)->getTipo()->is().compare(tts_e->getTs()->getTable().at(i)->getTipo()->is())!=0){
							stringstream out;
							out<<"Los Registros No tienen la misma estructura"<<endl;
							throw exception(out.str().c_str());
						}else{
							if(tts_v->getTs()->getTable().at(i)->getTipo()->is().compare("REGISTRO")==0){

								registro *a = (registro*)tts_v->getTs()->getTable().at(i)->getTipo();
								registro *b = (registro*)tts_e->getTs()->getTable().at(i)->getTipo();
								validarRegistros(a,b);

							}else{
								if(tts_v->getTs()->getTable().at(i)->getTipo()->is().compare("ARREGLO")==0){
									arreglo *a = (arreglo*)tts_v->getTs()->getTable().at(i)->getTipo();
									arreglo *b = (arreglo*)tts_e->getTs()->getTable().at(i)->getTipo();
									if(a->getTipo()->is().compare(b->getTipo()->is())==0){
										if(a->getTipo()->is().compare("REGISTRO")==0){
											registro *c = (registro*)a->getTipo();
											registro *d = (registro*)b->getTipo();
											validarRegistros(c,d);

										}
									}else{
									stringstream out;
									out<<"Tipos de Datos No son Compatibles"<<endl;
									throw exception(out.str().c_str());
									}

								}

							}
						}
					}

					

				}else{
					stringstream out;
					out<<"Los Registros No tienen la misma estructura"<<endl;
					throw exception(out.str().c_str());
				}
	}


	virtual tipo_ts * validarSemantica(tabla_simbolos *tabla_de_tipo,tabla_simbolos *tabla_de_varaible){
		tipo_ts *ttsV = this->variable->validarSemantica(tabla_de_tipo,tabla_de_varaible);
		tipo_ts *ttsE= this->expr->validarSemantica(tabla_de_tipo,tabla_de_varaible);
		if(ttsV->is().compare(ttsE->is())==0){
			if(ttsV->is().compare("REGISTRO")==0){
				registro *tts_v = (registro*)ttsV;
				registro *tts_e = (registro*)ttsE;
				validarRegistros(tts_v,tts_e);

			}
			if(ttsV->is().compare("ARREGLO")==0){
									arreglo *a = (arreglo*)ttsV;
									arreglo *b = (arreglo*)ttsV;
									if(a->getTipo()->is().compare(b->getTipo()->is())==0){
										if(a->getTipo()->is().compare("REGISTRO")==0){
											registro *c = (registro*)a->getTipo();
											registro *d = (registro*)b->getTipo();
											validarRegistros(c,d);

										}
									}else{
									stringstream out;
									out<<"Tipos de Datos No son Compatibles "<< this->getVariable()->getValor()<<endl;
									throw exception(out.str().c_str());
									}

								}

			
			
		}else{
			if((ttsV->is().compare("ENTERO")==0 || ttsV->is().compare("REAL")==0) && (ttsE->is().compare("ENTERO")==0 || ttsE->is().compare("REAL")==0)){
				
			}else{
				stringstream out;
				out<<"Tipos de Datos No son Compatibles "<< this->getVariable()->getValor()<<endl;
				throw exception(out.str().c_str());
			}
			
		}
		if(this->getNext()!=0){
		this->getNext()->SetReturn(this->GetReturn());
		this->getNext()->validarSemantica(tabla_de_tipo,tabla_de_varaible);
		
		}
		return ttsV;
	}

private:
	Variable* variable;
	Expr* expr;
	
};

